/*
 * edulisp_scanner.cpp
 *
 *  Created on: 07.04.2011
 *      Author: Дворников А.А.
 *              Миночкина Н.О.
 *              Моисеев А.И.
 *
 *      Revision: 292
 */

#include "edulisp_scanner.hpp"
//Локальные инклады

enum SSM_State {
    SSMS_S = 1,  // Начальное состояние
    SSMS_L,  // Идентификатор
    SSMS_D,  // Целое число
    SSMS_D2, // Дробная часть числа
    SSMS_CI, // Операторы?
    SSMS_Q,  // Строковая константа
    SSMS_E,
    SSMS_C1, // Строчный комментарий
	SSMS_C2,
	SSMS_C3, // Многострочный комментарий
	SSMS_C4,
	SSMS_C5,
	//
	//
	SSMS_ED, // Конечное состояние
	SSMS_E1,
	SSMS_E2,
	SSMS_E3,
	SSMS_E4,
	SSMS_E5,  // Необрабатываемый символ в коде программы
	SSMS_E6
};
//Состояния конечного автомата сканера

enum SSM_HL_State {
	SSMS_HL_NORMAL,
	SSMS_HL_WaitForFunction,
	SSMS_HL_IfCond,
	SSMS_HL_IfTrue,
	SSMS_HL_IfFalse,
	SSMS_HL_IfEnd
};

enum SSM_Event { SSME_LETTER, SSME_DIGIT, SSME_DOT, SSME_DECORATION, SSME_EOF,
	SSME_QUOTE, SSME_BACKSLASH, SSME_SEMICOLON, SSME_SLASH, SSME_CHARID,
	SSME_BRACKET_CLOSING, SSME_LINEFEED, SSME_CARRIEGERETURN, SSME_SPACE,
	SSME_SHARP, SSME_OPERATOR, SSME_CHARFUNCTION, SSME_ELSE, SSME_OTHER };
//События конечного автомата сканера

// Получение идентификатора
static int GetOperatorID(string& Operator)
{
	if (Operator == "(") return SSMO_BRACKET;
	if (Operator == ".") return SSMO_DOT;
	if (Operator == ")") return SSMO_BRACKET_CLOSING;
	if (Operator == "defun") return SSMO_USERFUNC;
	if (Operator == "lambda") return SSMO_LAMBDA;
	if (Operator == "cond") return SSMO_COND;
	if (Operator == "if") return SSMO_IF;
	return 0;
}

class SSM;

//Действие конечного автомата
typedef void (*SSM_Action)(SSM& StateMachine);

//typedef SSM_Action* SSM_ActionList;

struct SSM_Transition
{
	int BaseState;
	int Event;
	int TargetState;
	const SSM_Action *ActionList;
};

/*
struct SM_Transition
{
    SM_Transition() { TargetState = SSMS_EF; SSM_A = NULL; SSM_B = NULL; }
    void operator() (SSM_States target, SSM_Action ssma = NULL, SSM_Action ssmb = NULL)
    {
        TargetState = target;
        SSM_A = ssma;
        SSM_B = ssmb;
    }
    SSM_States TargetState;
    SSM_Action SSM_A, SSM_B; // Spaceship Broken - Parts Needed
};*/

//static SM_Transition SM_Edulisp[SSMS_EF][SSME_OTHER + 1];

typedef SSM_Transition* SSM_TransitionTable;

class SSM
{
private:
	int Q;     // текущее состояние
	const int EndState;
	const int *ErrorStates;
	unsigned int CurrentCharIndex;
	string Buf;
	//stringstream Buf;
	const SSM_Transition *P;
	const unsigned int P_length;
	LexemeList *LL;
	NameTable *NT;
	const int *Vocab;
	unsigned char CurrentChar;
	int Function;
	unsigned int BracketCounter, DefunBracketCounter;
	bool WaitForFunction;
	bool UserFunction;
	bool Defun;
	unsigned int LambdaArguments;
	SSM_HL_State HL_State;
	int InsertAddress;
	int OriginAddress;
public:
	SSM(int StartState, const SSM_Transition *TransitionTable,
			unsigned int TransitionTableLength, int *Vocab,
			int EndState_, const int *ErrorStates_, LexemeList& lLexemeList,
			NameTable& mNameTable);
	void Do(int Event);
	int Finished();
	void RollbackChar();
	unsigned int GetCurrentCharIndex();
	int GetCurrentState();
	void AddCharToBuf();
	void AddIdent();
	void ClearBuffer();
	void AddInteger();
	void AddFloat();
	void AddString();
	void AddFunction();
	string ParseEscape(string& sText);
	void AddOperator();
	int Parse(string& Text);
protected:
};

SSM::SSM(int StartState, const SSM_Transition *TransitionTable,
		const unsigned int TransitionTableLength, int *Vocab_,
		int EndState_, const int *ErrorStates_, LexemeList& lLexemeList,
		NameTable& mNameTable)
	: Q(StartState), EndState(EndState_), ErrorStates(ErrorStates_),
	  CurrentCharIndex(0), P(TransitionTable), P_length(TransitionTableLength),
	  LL(&lLexemeList), NT(&mNameTable), Vocab(Vocab_), Function(-1),
	  BracketCounter(0), DefunBracketCounter(0), WaitForFunction(false),
	  UserFunction(false), Defun(false), LambdaArguments(false),
	  HL_State(SSMS_HL_NORMAL)
{
	lLexemeList.clear();
	mNameTable.clear();
	//mNameTable.push_back(Buf);
}

void SSM::Do(int Event)
{
	/*
    // ELSE-переход
    if (SM_Edulisp[Q][Event].TargetState == SSMS_EF) Event = SSME_OTHER;

    // AREN'T NICE
    if (SM_Edulisp[Q][Event].SSM_A)
        (*SM_Edulisp[Q][Event].SSM_A)(*this);

    if (SM_Edulisp[Q][Event].SSM_B)
        (*SM_Edulisp[Q][Event].SSM_B)(*this);

    Q = SM_Edulisp[Q][Event].TargetState;

    CurrentCharIndex++;
	*/

	const SSM_Transition *T = P;
	const SSM_Transition *ST = NULL;
	for (unsigned int i = 0; i < P_length; i++, T++)
	{
		if (T->BaseState == Q)
		{
			if ((T->Event == SSME_ELSE) || (T->Event == Event))
				ST = T;
			if (T->Event == Event)
				break;
		}
	}
	if (ST)
	{
		const SSM_Action *Action = ST->ActionList;
		if (Action)
			while(*Action)
				(*Action++)(*this);

		Q = ST->TargetState;
	}

	CurrentCharIndex++;
}

int SSM::Parse(string& Text)
{
	int Result;
	while(!(Result = Finished()))
	{
		if (CurrentCharIndex > Text.length())
			return SEC_INTERNAL;

		CurrentChar = Text[CurrentCharIndex];
		Do(Vocab[CurrentChar]);
	}

	return Result;
}

int SSM::Finished()
{
	if (Q == EndState)
		return 1;
	for(const int *i = ErrorStates; *i; i++)
		if (Q == *i)
			return 2;

	return 0;
}

void SSM::RollbackChar()
{
	CurrentCharIndex--;
}

unsigned int SSM::GetCurrentCharIndex()
{
	return CurrentCharIndex;
}

int SSM::GetCurrentState()
{
	return Q;
}

void SSM::ClearBuffer()
{
	Buf.clear();
}

void SSM::AddCharToBuf()
{
	Buf += CurrentChar;
}

void SSM::AddIdent()
{
	//
	if ((Buf == "lambda") || Defun)
	{
		if (Defun)
		{
			// занесение идентификатора функции
			NT->push_back(new NameTable_Entry(&Buf, LT_ID));
			Defun = false;
			ClearBuffer();
		}
		else
		{
			NT->push_back(new NameTable_Entry(NULL, LT_ID));
			AddOperator();
		}
		Function = NT->size() - 1; // текущий id владельца
		DefunBracketCounter = 1; // обнуляем счетчик скобок для сравнения
		UserFunction = true;
		WaitForFunction = true;  // ввод параметров
		                         // (до первой закрывающей скобки)

		LL->push_back(Function);
		return;
	}
	if (Buf == "defun")
	{
		LL->pop_back();
		AddOperator();
		Defun = true; // ожидание имени функции
		return;
	}

	// Вот эти два ифа надо заменить на что-то поцивильней, потому как
	// аналогичное действие выполняется в GetOperatorID
	if (Buf == "cond")
	{
		AddOperator();
		return;
	}

	if (Buf == "if")
	{
		LL->pop_back();
		AddOperator();
		BracketCounter = 0;
		HL_State = SSMS_HL_IfCond;
		return;
	}

	// -- неключевое слово --
	int index;

	// WaitForFunction - список аргументов, безоговорочно вносим новые записи
	// в таблицу имен (хотя неплохо было бы отсекать совпадения имен в
	// списке переменных)
	if (WaitForFunction)
	{
		NT->push_back(new NameTable_Entry(Buf, Function));
		index = NT->size() - 1;
	}
	// Иначе - поиск в таблице имен с приоритетом на владельца
	else
		if ((index = NT->NameIndex( Buf, UserFunction ? Function : -1)) == -1)
		{
			NT->push_back(new NameTable_Entry(Buf));
			index = NT->size() - 1;
		}

	LL->push_back(index);
//	WaitForFunction = false;
	switch(HL_State)
	{
	case SSMS_HL_IfCond:
		if (!BracketCounter)
		{
			InsertAddress = LL->size();
			OriginAddress = LL->size();
			//Эту лексему мы заменим на адрес инструкции для второго случая
			LL->push_back(888);
			HL_State = SSMS_HL_IfTrue;
		}
		break;
	default:
		break;
	}
	ClearBuffer();
}

void SSM::AddInteger()
{
	int index;
	if ((index = NT->NameIndex(Buf)) == -1)
	{
		int ints;
		istringstream is(Buf);
		is >> ints;
		NT->push_back(new NameTable_Entry(&Buf, LT_CONST, ints));
		index = NT->size() - 1;
	}
	LL->push_back(index);
	ClearBuffer();
}

// !!! При высокой точности возникает ошибка сегментации !!!
void SSM::AddFloat()
{
	int index;
	if ((index = NT->NameIndex(Buf)) == -1)
	{
		double flts;
		istringstream is(Buf);
		is >> flts;
		NT->push_back(new NameTable_Entry(&Buf, LT_CONST, flts));
		index = NT->size() - 1;
	}
	LL->push_back(index);
	ClearBuffer();
}

void SSM::AddString()
{
	int index;
	string ParsedValue = ParseEscape(Buf);
	if ((index = NT->StringValueIndex(ParsedValue)) == -1)
	{
		NT->push_back(new NameTable_Entry(LT_CONST, ParsedValue));
		index = NT->size() - 1;
	}
	LL->push_back(index);
	ClearBuffer();
}

void SSM::AddOperator()
{
    //LL->push_back("OPERATOR=" + Buf);
	int Operator = GetOperatorID(Buf);
	LL->push_back(-Operator);

	// удаление лишней открывающей скобки
	// в крайнем случае, можно добавить переменную для "недобавления"
	// только вот получается, что открывающие скобки внутри списка параметров
	// игнорируются
	if (Operator == SSMO_BRACKET)
	{
		if (WaitForFunction)
			LL->pop_back();

		++BracketCounter;
		++DefunBracketCounter;
	}
	else
		if (Operator == SSMO_BRACKET_CLOSING)
		{
			--BracketCounter;
			--DefunBracketCounter;

			if (UserFunction && !DefunBracketCounter) UserFunction = false;

			if (WaitForFunction)
				WaitForFunction = false;

			switch(HL_State)
			{
			case SSMS_HL_IfCond:
				if (!BracketCounter)
				{
					InsertAddress = LL->size();
					OriginAddress = LL->size();
					//Эту лексему мы заменим на адрес инструкции для второго случая
					LL->push_back(0);
					HL_State = SSMS_HL_IfTrue;
				}
				break;
			case SSMS_HL_IfTrue:
				if (!BracketCounter)
				{
					HL_State = SSMS_HL_IfFalse;
					(*LL)[InsertAddress] = -((LL->size() + 1) - OriginAddress);
					InsertAddress = LL->size();
					OriginAddress = LL->size();
					LL->push_back(0);
				}
				break;
			case SSMS_HL_IfFalse:
				if (!BracketCounter)
				{
					HL_State = SSMS_HL_IfEnd;
					(*LL)[InsertAddress] = -(LL->size() - OriginAddress);
				}
				break;
			case SSMS_HL_IfEnd:
				HL_State = SSMS_HL_NORMAL;
				LL->pop_back();
				break;
			default:
				break;
			}
		}

    ClearBuffer();
}

string SSM::ParseEscape(string& sText)
{
	string Buf;
	bool EscapeFlag = false;
	for(unsigned int i = 0; i < sText.length(); i++)
	{
		if (!EscapeFlag)
		{
			if (sText[i] == '\\')
				EscapeFlag = true;
			else
				Buf += sText[i];
		}
		else
		{
			switch(sText[i])
			{
			case 'n':
				Buf += '\n';
				break;
			case 'r':
				Buf += '\r';
				break;
			case 't':
				Buf += '\t';
				break;
			default:
				Buf += sText[i];
			}

			EscapeFlag = false;
		}
	}

	return Buf;
}

//--------- Transition actions -----------------//

void ClearBuffer(SSM& StateMachine)
{
	StateMachine.ClearBuffer();
}

void RollbackChar(SSM& StateMachine)
{
	StateMachine.RollbackChar();
}

void AddCharToBuf(SSM& StateMachine)
{
	StateMachine.AddCharToBuf();
}

void AddIdent(SSM& StateMachine)
{
	StateMachine.AddIdent();
}

void AddInteger(SSM& StateMachine)
{
	StateMachine.AddInteger();
}

void AddOperator(SSM& StateMachine)
{
    StateMachine.AddOperator();
}

void AddFloat(SSM& StateMachine)
{
	StateMachine.AddFloat();
}

void AddString(SSM& StateMachine)
{
	StateMachine.AddString();
}

/*
void SM_Populate()
{
    // SSMS_L
    SM_Edulisp[SSMS_S][SSME_LETTER] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_S][SSME_N] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_S][SSME_R] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_S][SSME_T] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_L][SSME_DIGIT] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_L][SSME_LETTER] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_L][SSME_N] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_L][SSME_R] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_L][SSME_T] (SSMS_L, &AddCharToBuf);
    SM_Edulisp[SSMS_L][SSME_LINEFEED] (SSMS_S, &AddIdent);
    SM_Edulisp[SSMS_L][SSME_CARRIEGERETURN] (SSMS_S, &AddIdent);
    SM_Edulisp[SSMS_L][SSME_SPACE] (SSMS_S, &AddIdent);
    SM_Edulisp[SSMS_L][SSME_BRACKET_CLOSING] (SSMS_S, &AddIdent, &RollbackChar);
    SM_Edulisp[SSMS_L][SSME_EOF] (SSMS_S, &AddIdent, &RollbackChar);
    SM_Edulisp[SSMS_L][SSME_OTHER] (SSMS_ED, &ErrorOut);

    // SSMS_D
    SM_Edulisp[SSMS_S][SSME_DIGIT] (SSMS_D, &ClearBuffer, &AddCharToBuf);
    SM_Edulisp[SSMS_D][SSME_DIGIT] (SSMS_D, &AddCharToBuf);
    SM_Edulisp[SSMS_D][SSME_LINEFEED] (SSMS_S, &AddInteger);
    SM_Edulisp[SSMS_D][SSME_CARRIEGERETURN] (SSMS_S, &AddInteger);
    SM_Edulisp[SSMS_D][SSME_SPACE] (SSMS_S, &AddInteger);
    SM_Edulisp[SSMS_D][SSME_BRACKET_CLOSING] (SSMS_S, &AddInteger, &RollbackChar);
    SM_Edulisp[SSMS_D][SSME_EOF] (SSMS_S, &AddInteger, &RollbackChar);
    SM_Edulisp[SSMS_D][SSME_SEMICOLON] (SSMS_S, &AddInteger, &RollbackChar);
    SM_Edulisp[SSMS_D][SSME_SLASH] (SSMS_S, &AddInteger, &RollbackChar);
    SM_Edulisp[SSMS_D][SSME_DOT] (SSMS_D2, &AddCharToBuf);
    SM_Edulisp[SSMS_D][SSME_OTHER] (SSMS_ED, &ErrorOut);

    // SSMS_D2
    SM_Edulisp[SSMS_D2][SSME_DIGIT] (SSMS_D2, &AddCharToBuf);
    SM_Edulisp[SSMS_D2][SSME_LINEFEED] (SSMS_S, &AddFloat);
    SM_Edulisp[SSMS_D2][SSME_CARRIEGERETURN] (SSMS_S, &AddFloat);
    SM_Edulisp[SSMS_D2][SSME_SPACE] (SSMS_S, &AddFloat);
    SM_Edulisp[SSMS_D2][SSME_BRACKET_CLOSING] (SSMS_S, &AddFloat, &RollbackChar);
    SM_Edulisp[SSMS_D2][SSME_EOF] (SSMS_S, &AddFloat, &RollbackChar);
    SM_Edulisp[SSMS_D2][SSME_OTHER] (SSMS_ED, &ErrorOut);
<<<<<<< .mine
    // SSMS_Q
    SM_Edulisp[SSMS_S][SSME_QUOTE] (SSMS_Q);
    SM_Edulisp[SSMS_Q][SSME_EOF] (SSMS_ED, &ErrorOut);
    SM_Edulisp[SSMS_Q][SSME_QUOTE] (SSMS_S, &AddString);
    SM_Edulisp[SSMS_Q][SSME_BACKSLASH] (SSMS_E);
    SM_Edulisp[SSMS_Q][SSME_OTHER] (SSMS_Q, &AddCharToBuf);

    // SSMS_E
    SM_Edulisp[SSMS_E][SSME_N] (SSMS_Q, &AddLineFeed);
    SM_Edulisp[SSMS_E][SSME_R] (SSMS_Q, &AddCarriegeReturn);
    SM_Edulisp[SSMS_E][SSME_T] (SSMS_Q, &AddTabulation);
    SM_Edulisp[SSMS_E][SSME_EOF] (SSMS_ED, &ErrorOut);
    SM_Edulisp[SSMS_E][SSME_OTHER] (SSMS_Q, &AddCharToBuf);

    // SSMS_C1
    SM_Edulisp[SSMS_S][SSME_SEMICOLON] (SSMS_C1);
    SM_Edulisp[SSMS_C1][SSME_LINEFEED] (SSMS_C2); // иначе ничего не делаем
    SM_Edulisp[SSMS_C2][SSME_CARRIEGERETURN] (SSMS_S);
    SM_Edulisp[SSMS_C2][SSME_OTHER] (SSMS_C1);

    // SSMS_C3
    SM_Edulisp[SSMS_S][SSME_SLASH] (SSMS_C3);
    SM_Edulisp[SSMS_C3][SSME_SHARP] (SSMS_C4);
    SM_Edulisp[SSMS_C4][SSME_SHARP] (SSMS_C5);
    SM_Edulisp[SSMS_C5][SSME_BACKSLASH] (SSMS_S);
    SM_Edulisp[SSMS_C5][SSME_OTHER] (SSMS_C4);

    // SSMS_S
    SM_Edulisp[SSMS_S][SSME_CHARID] (SSMS_S, &AddCharToBuf, &AddOperator);
    SM_Edulisp[SSMS_S][SSME_BRACKET_CLOSING] (SSMS_S, &AddCharToBuf, &AddOperator);
    SM_Edulisp[SSMS_S][SSME_SPACE] (SSMS_S);
    SM_Edulisp[SSMS_S][SSME_EOF] (SSMS_ED);
    SM_Edulisp[SSMS_S][SSME_OTHER] (SSMS_ED, &ErrorOut);
}
*/

static const SSM_Action AL_AddCharToBuf[] = { &AddCharToBuf, NULL };
static const SSM_Action AL_AddIdent[] = { &AddIdent, NULL };
static const SSM_Action AL_AddIdentAndRollback[] = { &AddIdent, &RollbackChar,
		NULL };
static const SSM_Action AL_AddInteger[] = { &AddInteger, NULL };
static const SSM_Action AL_AddIntegerAndRollback[] = { &AddInteger, &RollbackChar,
		NULL };
static const SSM_Action AL_AddFloat[] = { &AddFloat, NULL };
static const SSM_Action AL_AddFloatAndRollback[] = { &AddFloat, &RollbackChar,
		NULL };
static const SSM_Action AL_AddString[] = { &AddString, NULL };

static const SSM_Action AL_AddOperator[] = { &AddCharToBuf, &AddOperator, NULL };
static const SSM_Action AL_RollbackChar[] = { &RollbackChar, NULL };

static const SSM_Action AL_ClearBuffer[] = { &ClearBuffer, NULL };

static const SSM_Transition TT_EduLisp[] =
{
		//L
		{ SSMS_S, SSME_LETTER, SSMS_L, AL_AddCharToBuf },
		//{ SSMS_S, SSME_CHARFUNCTION, SSMS_L, AL_AddCharToBuf },
		{ SSMS_L, SSME_DIGIT, SSMS_L, AL_AddCharToBuf },
		{ SSMS_L, SSME_LETTER, SSMS_L, AL_AddCharToBuf },
		{ SSMS_L, SSME_LINEFEED, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_DECORATION, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_CARRIEGERETURN, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_SPACE, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_BRACKET_CLOSING, SSMS_S, AL_AddIdentAndRollback },
		//{ SSMS_L, SSME_CHARFUNCTION, SSMS_E6, NULL },
		{ SSMS_L, SSME_EOF, SSMS_S, AL_AddIdentAndRollback },
		{ SSMS_L, SSME_ELSE, SSMS_E1, NULL },
		//END L

		//D
		{ SSMS_S, SSME_DIGIT, SSMS_D, AL_AddCharToBuf },
		{ SSMS_D, SSME_DIGIT, SSMS_D, AL_AddCharToBuf },
		{ SSMS_D, SSME_LINEFEED, SSMS_S, AL_AddInteger },
		{ SSMS_D, SSME_CARRIEGERETURN, SSMS_S, AL_AddInteger },
		{ SSMS_D, SSME_SPACE, SSMS_S, AL_AddInteger },
		{ SSMS_D, SSME_BRACKET_CLOSING, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_EOF, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_SEMICOLON, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_DOT, SSMS_D2, AL_AddCharToBuf },
		{ SSMS_D, SSME_SLASH, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_ELSE, SSMS_E2, NULL },
		//END D


		//D2
		{ SSMS_D2, SSME_DIGIT, SSMS_D2, AL_AddCharToBuf },
		{ SSMS_D2, SSME_LINEFEED, SSMS_S, AL_AddFloat },
		{ SSMS_D2, SSME_CARRIEGERETURN, SSMS_S, AL_AddFloat },
		{ SSMS_D2, SSME_SPACE, SSMS_S, AL_AddFloat },
		{ SSMS_D2, SSME_BRACKET_CLOSING, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_EOF, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_SEMICOLON, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_SLASH, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_ELSE, SSMS_E2, NULL },
		//END D2

		//Q
		{ SSMS_S, SSME_QUOTE, SSMS_Q, NULL },
		{ SSMS_Q, SSME_EOF, SSMS_E3, NULL },
		{ SSMS_Q, SSME_QUOTE, SSMS_S, AL_AddString },
		{ SSMS_Q, SSME_SLASH, SSMS_E, AL_AddCharToBuf },
		{ SSMS_Q, SSME_ELSE, SSMS_Q, AL_AddCharToBuf },
		//END Q

		//E
		{ SSMS_E, SSME_ELSE, SSMS_Q, AL_AddCharToBuf },
		//END E

		//C1
		{ SSMS_S, SSME_SEMICOLON, SSMS_C1, NULL },
        { SSMS_C1, SSME_LINEFEED, SSMS_C2, NULL },
        { SSMS_C1, SSME_EOF, SSMS_S, AL_RollbackChar },
        //END C1

        //C2
        { SSMS_C2, SSME_CARRIEGERETURN, SSMS_S, NULL },
		{ SSMS_C2, SSME_ELSE, SSMS_C1, NULL },
		//END C1

		//C3
        { SSMS_S, SSME_SLASH, SSMS_C3, AL_AddCharToBuf },
        { SSMS_C3, SSME_SHARP, SSMS_C4, AL_ClearBuffer },
        { SSMS_C3, SSME_SPACE, SSMS_S, AL_AddIdent },
        { SSMS_C3, SSME_EOF, SSMS_S, AL_AddIdent },
        //{ SSMS_C3, SSME_ELSE, SSMS_E6, NULL },
        { SSMS_C3, SSME_ELSE, SSMS_L, AL_RollbackChar },
        //END C3

        //C4
        { SSMS_C4, SSME_SHARP, SSMS_C5, NULL },
        { SSMS_C4, SSME_EOF, SSMS_E4, NULL },
        //END C4

        //END C5
        { SSMS_C5, SSME_SLASH, SSMS_S, NULL },
		{ SSMS_C5, SSME_ELSE, SSMS_C4, NULL },
		//END C5

		//S
		{ SSMS_S, SSME_OPERATOR, SSMS_S, AL_AddOperator },
		{ SSMS_S, SSME_BRACKET_CLOSING, SSMS_S, AL_AddOperator },
		{ SSMS_S, SSME_DOT, SSMS_S, AL_AddOperator },
		{ SSMS_S, SSME_OTHER, SSMS_E5, NULL },
		//END S

		{ SSMS_S, SSME_EOF, SSMS_ED, NULL }
};

static const int ErrorStates[] = { SSMS_E1, SSMS_E2, SSMS_E3, SSMS_E4, SSMS_E5,
		SSMS_E6, NULL };

/*
SSM_Event GetEvent(char Char)
{

	if ((Char >= '0') && (Char <= '9')) return SSME_DIGIT;

	switch(Char)
	{
    case '+': case '-': case '*': case '=': case '!': case '%': case '_':
        return SSME_LETTER;
	case '\0':
		return SSME_EOF;
	case ')':
		return SSME_BRACKET_CLOSING;
	case '\t':
		return SSME_DECORATION;
	case ' ':
		return SSME_SPACE;
	case '\n':
		return SSME_LINEFEED;
	case '\r':
		return SSME_CARRIEGERETURN;
	case '.':
		return SSME_DOT;
	case '\"':
		return SSME_QUOTE;
	case '\\':
		return SSME_BACKSLASH;
	case ';':
		return SSME_SEMICOLON;
	case '/':
		return SSME_SLASH;
	case '#':
		return SSME_SHARP;
	case '(': case '@':
		return SSME_CHARID;
	}

    if (((Char >= 'A') && (Char <= 'Z')) || ((Char >= 'a') && (Char <= 'z')))
        return SSME_LETTER;

	return SSME_OTHER;
}
*/

int Scan(string& sText, LexemeList& lLexemeList, NameTable& mNameTable,
		TextFormat eTextFormat)
{
    //SM_Populate();
	int Vocablurary[sizeof(char) * 256];
	//memset(Vocablurary, SSME_OTHER, sizeof(Vocablurary));
	for(unsigned int i = 0; i < sizeof(char) * 256; i++)
		Vocablurary[i] = SSME_OTHER;
	Vocablurary['+'] = Vocablurary['-'] = Vocablurary['*'] = Vocablurary['='] =
			//Vocablurary['!'] = Vocablurary['%'] = SSME_CHARFUNCTION;
			Vocablurary['!'] = Vocablurary['%'] = Vocablurary['_'] =
			Vocablurary['<'] = SSME_LETTER;
	Vocablurary['\0'] = SSME_EOF;
	Vocablurary[')'] = SSME_BRACKET_CLOSING;
	Vocablurary['\t'] = SSME_DECORATION;
	Vocablurary[' '] = SSME_SPACE;
	Vocablurary['\n'] = SSME_LINEFEED;
	Vocablurary['\r'] = SSME_CARRIEGERETURN;
	Vocablurary['.'] = SSME_DOT;
	Vocablurary['\"'] = SSME_QUOTE;
	Vocablurary['\\'] = SSME_SLASH;
	Vocablurary[';'] = SSME_SEMICOLON;
	Vocablurary['/'] = SSME_SLASH;
	Vocablurary['#'] = SSME_SHARP;
	Vocablurary['('] = SSME_OPERATOR;
	Vocablurary[0xFF] = SSME_DECORATION;
	for(unsigned int i = 'A'; i <= 'Z'; i++)
		Vocablurary[i] = SSME_LETTER;
	for(unsigned int i = 'a'; i <= 'z'; i++)
		Vocablurary[i] = SSME_LETTER;
	Vocablurary['_'] = SSME_LETTER;
	for(unsigned int i = '0'; i <= '9'; i++)
		Vocablurary[i] = SSME_DIGIT;

	SSM Scanner(SSMS_S, TT_EduLisp, sizeof(TT_EduLisp) / sizeof(SSM_Transition),
			Vocablurary, SSMS_ED, ErrorStates, lLexemeList, mNameTable);
	//Конечный автомат сканера

	return Scanner.Parse(sText);
}
